package com.timofeyco.springsocialwithscribedemo.social.facebook.impl;

import com.timofeyco.springsocialwithscribedemo.social.OAuth2Manager;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * Product: Spring Social with Scribe demo
 * Author: Timofey Tatarinov
 * Date: 9/21/11
 * Time: 10:46 PM
 */
public class FacebookOAuthManager implements OAuth2Manager {
    protected String secret;
    protected String clientId;
    protected String redirectURI;

    protected String crawlToURL(URL uri) {
        ByteArrayOutputStream byteOutputStream = null;
        InputStream inputStream = null;
        String stream = null;

        try {
            inputStream = uri.openStream();
            byteOutputStream = new ByteArrayOutputStream();
            int i;
            while ((i = inputStream.read()) != -1) {
                byteOutputStream.write(i);
            }
            stream = new String(byteOutputStream.toByteArray());

        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (null != byteOutputStream) {
                try {
                    byteOutputStream.close();
                } catch (IOException e) {
                    //do some logging here instead of printStackTrace()
                    e.printStackTrace();
                }
            }

            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    //do some logging here instead of printStackTrace()
                    e.printStackTrace();
                }
            }
        }
        return stream;
    }

    private final String AUTHORIZE_URI = "https://www.facebook.com/dialog/oauth";
    private final String ACCESS_TOKEN_URI = "https://graph.facebook.com/oauth/access_token";

    public void setSecret(String secret) {
        this.secret = secret;
    }

    public void setClientId(String clientId) {
        this.clientId = clientId;
    }

    public void setRedirectURI(String redirectURI) {
        this.redirectURI = redirectURI;
    }

    protected String assembleAuthentication(String authCode) {
        return getAccessTokenBaseUrl() + "?" +
                "client_id=" + clientId + "&" +
                "redirect_uri=" + redirectURI + "&" +
                "client_secret=" + secret + "&" +
                "code="  + authCode;
    }

    public String loginAuthenticate() {
        return "redirect:" + getAuthorizeBaseUrl() + "?" +
                "client_id=" + clientId + "&" +
                "display=page&redirect_uri=" + redirectURI + "&" +
                "scope=email,read_stream,offline_access";

    }

    public String retrieveAccessToken(String code) {
        String accessToken = null;
        if (null != code) {
            String authURL = assembleAuthentication(code);
            URL uri = null;
            try {
                uri = new URL(authURL);
                String result = crawlToURL(uri);
                String[] values  = result.split("&");
                for (String value: values) {
                    String[] valuePair = value.split("=");
                    if (valuePair.length != 2) {
                        throw new RuntimeException("Unexpected auth response");
                    } else {
                        if (valuePair[0].equals("access_token")) {
                            accessToken = valuePair[1];
                            break;
                        }
                    }
                }
            } catch (MalformedURLException ex) {
                throw  new RuntimeException(ex);
            }
        }
        return accessToken;
    }

    public String getAuthorizeBaseUrl() {
        return AUTHORIZE_URI;
    }

    public String getAccessTokenBaseUrl() {
        return ACCESS_TOKEN_URI;
    }


}
